package com.tao.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.tao.context.UserContext;
import com.tao.mapper.OrderDetailMapper;
import com.tao.mapper.OrderStoreMapper;
import com.tao.mapper.UserMapper;
import com.tao.pojo.dto.OrderCancelDto;
import com.tao.pojo.dto.OrderRejectDto;
import com.tao.pojo.dto.PageSearchOrtderDto;
import com.tao.pojo.entity.Order;
import com.tao.pojo.entity.OrderConfirmDto;
import com.tao.pojo.entity.OrderDetail;
import com.tao.pojo.vo.OrderSearchVo;
import com.tao.pojo.vo.OrderStatisticVo;
import com.tao.pojo.vo.OrderVo;
import com.tao.result.PageResult;
import com.tao.service.OrderStoreService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class OrderStoreService1 implements OrderStoreService {
    @Autowired
    OrderStoreMapper orderStoreMapper;
    @Autowired
    OrderDetailMapper orderDetailMapper;
    @Autowired
    UserMapper userMapper;

    @Override
    public PageResult orderSearch(PageSearchOrtderDto pageSearchOrtderDto) {
        log.info("接收到的参数为:{}", pageSearchOrtderDto);
        PageHelper.startPage(pageSearchOrtderDto.getPage(), pageSearchOrtderDto.getPageSize());
        Page<OrderSearchVo> page = orderStoreMapper.orderSearch(pageSearchOrtderDto);

        //要求以字符串形式显示菜品详情
        page.forEach(orderSearchVo -> {
            orderSearchVo.setOrderProducts(getOrderProductsStr(orderSearchVo));
            orderSearchVo.setUserName(userMapper.getUserByIdMapper(UserContext.getThreadUserId()).getName());
        });
        PageResult pageResult = new PageResult(page.getTotal(), page.getResult());
        return pageResult;
    }

    /**
     * 根据订单id获取菜品信息字符串
     *
     * @param orderSearchVo
     * @return
     */
    private String getOrderProductsStr(OrderSearchVo orderSearchVo) {
        //将各种信息拼接在一起思路：先获得集合，再转为字符串
        // 查询订单菜品详情信息（订单中的菜品和数量）
        List<OrderDetail> orderDetailList = orderDetailMapper.getOrderDetail(orderSearchVo.getId());

        // 将每一条订单菜品信息拼接为字符串（格式：宫保鸡丁*3；）
        // 根据一个集合生成另一个集合-->流map
        List<String> orderDishList = orderDetailList.stream().map(x -> {
            String orderDish = x.getName() + "*" + x.getNumber() + ";";
            return orderDish;
        }).collect(Collectors.toList()) ;

        // 将该订单对应的所有菜品信息拼接在一起  利用join将集合转为字符串
        return String.join(" ", orderDishList);
    }

    @Override
    public OrderStatisticVo orderStatisticStatus() {
        OrderStatisticVo orderStatisticVo = new OrderStatisticVo();
        orderStatisticVo.setConfirmed(orderStoreMapper.orderStatisticStatus(null,null,Order.CONFIRMED));
        orderStatisticVo.setToBeConfirmed(orderStoreMapper.orderStatisticStatus(null,null,Order.TO_BE_CONFIRMED));
        orderStatisticVo.setDeliveryInProgress(orderStoreMapper.orderStatisticStatus(null,null,Order.DELIVERY_IN_PROGRESS));
        return orderStatisticVo;
    }

    @Override
    public OrderVo getOrderDetail(Integer id) {
        //像这种vo里有list的只能调用多个mapper，无法多表查询，因为无法根据名字封装
        Integer userId = UserContext.getThreadUserId();
        log.info("查询用户:{}的:{}订单详细信息", userId, id);
        Order order = orderStoreMapper.getOrderById(id);
        OrderVo orderVo = new OrderVo();
        BeanUtils.copyProperties(order,orderVo);
        orderVo.setUserName(userMapper.getUserByIdMapper(userId).getName());
        orderVo.setOrderDetailList(orderDetailMapper.getOrderDetail(id));
        log.info("完整订单信息为:{}", orderVo);
        return orderVo;
    }

    @Override
    public void rejectionOrder(OrderRejectDto orderRejectDto) {
        //本质为修改操作，可以统一利用一个接口

        log.info("接收到的参数为:{}",orderRejectDto);
        //仅用于判断
        Order order = orderStoreMapper.getOrderById(orderRejectDto.getId());
        //为了提高修改速度，新建一个实体，修改哪些给哪些字段赋值
        Order order1 = new Order();

        //实际的额外逻辑操作
        // 订单只有存在且状态为2（待接单）才可以拒单 由于最后操作数据库，这里都是判异常和赋值等逻辑操作
        if (order == null || order.getStatus() != Order.TO_BE_CONFIRMED) {
            throw new RuntimeException("订单不存在或已经接单，无法拒单");
        }

        //如果以付款需要退款
        if (order.getPayStatus() == Order.PAID) {
            //用户已支付，需要退款
//            String refund = weChatPayUtil.refund(
//                    ordersDB.getNumber(),
//                    ordersDB.getNumber(),
//                    new BigDecimal(0.01),
//                    new BigDecimal(0.01));
//            log.info("申请退款：{}", refund);
            order1.setPayStatus(Order.REFUND);
            log.info("退款成功");
        }

        //最后操作数据库 注意：！！最后！！

        order1.setId(orderRejectDto.getId());
        order1.setRejectionReason(orderRejectDto.getRejectionReason());
        order1.setStatus(Order.CANCELLED);

        order1.setCancelTime(LocalDateTime.now());
        log.info("需要修改的信息为:{}",order1);
        orderStoreMapper.updateOrder(order1);

    }

    @Override
    public void cancelOrder(OrderCancelDto orderCancelDto) {
        log.info("接收到的参数为:{}",orderCancelDto);
        //任何修改都需要判空
        Order order = orderStoreMapper.getOrderById(orderCancelDto.getId());
        //节省修改速度，只给需要的赋值
        Order order1 = new Order();

        //处理异常情况
        if(order == null  || order.getStatus()==Order.TO_BE_CONFIRMED){
            throw new RuntimeException("订单不存在，无法取消");
        }

        //若已经付款需要退款
        if (order.getStatus()==Order.PAID){
//            String refund = weChatPayUtil.refund(
//                    ordersDB.getNumber(),
//                    ordersDB.getNumber(),
//                    new BigDecimal(0.01),
//                    new BigDecimal(0.01));
//            log.info("申请退款：{}", refund);
            log.info("退款成功");
            order1.setPayStatus(Order.REFUND);
        }

        order1.setId(orderCancelDto.getId());
        order1.setCancelTime(LocalDateTime.now());
        order1.setCancelReason(orderCancelDto.getCancelReason());
        order1.setStatus(Order.CANCELLED);
        log.info("需要修改的信息为:{}",order1);
        orderStoreMapper.updateOrder(order1);
        log.info("订单取消成功");
    }

    @Override
    public void confirmOrder(OrderConfirmDto orderConfirmDto) {
        log.info("接收到的参数为：{}",orderConfirmDto);

        Order order = orderStoreMapper.getOrderById(orderConfirmDto.getId());
        Order order1 = new Order();

        if(order == null ){
            throw new RuntimeException("该订单不存在");
        }

        order1.setStatus(Order.CONFIRMED);
        order1.setId(orderConfirmDto.getId());
        log.info("需要修改的信息为:{}",order1);
        orderStoreMapper.updateOrder(order1);
        log.info("修改成功");
    }

    @Override
    public void deliveryOrder(Integer id) {
        log.info("前端传来的信息为:{}",id);

        Order order = orderStoreMapper.getOrderById(id);
        Order order1 = new Order();

        if (order==null || !Objects.equals(order.getStatus(), Order.CONFIRMED)){
            throw new RuntimeException("商品不存在或处于无法配送状态");
        }

        order1.setId(id);
        order1.setStatus(Order.DELIVERY_IN_PROGRESS);
        log.info("需要修改的信息为:{}",order1);
        orderStoreMapper.updateOrder(order1);
        log.info("修改成功");
    }

    @Override
    public void completeOrder(Integer id) {
        log.info("传来的信息为:{}",id);

        Order order = orderStoreMapper.getOrderById(id);
        Order order1 = new Order();

        if (order==null || !Objects.equals(order.getStatus(), Order.DELIVERY_IN_PROGRESS)){
            throw new RuntimeException("商品不存在或处于无法配送状态");
        }

        order1.setId(id);
        order1.setStatus(Order.COMPLETED);
        order1.setDeliveryTime(LocalDateTime.now());
        log.info("需要修改的信息为:{}",order1);
        orderStoreMapper.updateOrder(order1);
        log.info("修改成功");
    }
}
